package com.example.mybank.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mybank.config.CloseConfig;
import com.example.mybank.entity.*;
import com.example.mybank.mapper.*;
import com.example.mybank.kafka.Producer;
import com.example.mybank.service.BuycountService;
import com.example.mybank.service.EngineService;
import com.example.mybank.tool.RedisTool;
import com.example.mybank.tool.ResultCode;
import com.example.mybank.tool.MyException;

import com.example.mybank.springSecurity.UserHandler;
import com.example.mybank.tool.TokenHelper;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("/product")
public class ProductController {

    @Autowired
    ProductMapper productMapper;

    @Autowired
    OrdersMapper ordersMapper;

    @Autowired
    EngineMapper engineMapper;


    @Autowired
    CloseConfig closeConfig;
    // 紧密相关的生产者
    @Autowired
    Producer producer;

    @Autowired
    BuycountMapper buycountMapper;

    @Autowired
    EngineService engineService;

    @Autowired
    AccountMapper accountMapper;

    @Autowired
    BuycountService buycountService;

    @Resource
    private KafkaTemplate<String, Integer> kafkaTemplate;

    // 管理员：获取所有产品
    @GetMapping("/all")
    public List<Product> getAll(){
        return productMapper.selectList(null);
    }

    /**
     * 开始时间等于传入时间的
     * @param timestamp
     * @return
     */
    @GetMapping("/time/{timestamp}")
    public List<Product> getByTime(@PathVariable("timestamp") long timestamp){
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("time_from",new Date(timestamp));
        return productMapper.selectList(queryWrapper);
    }

    @GetMapping("/buyable")
    public List<Product> getBuyable(){
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        Date nowTime = new Date(System.currentTimeMillis());
        return productMapper.selectList(queryWrapper);
    }

    @GetMapping("/get/{productID}")
    public List<Product> getById(@PathVariable("productID") int productID){
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",productID);
        return productMapper.selectList(queryWrapper);
    }

    /**
     * 新增产品
     * @param product
     * @return
     */
    @PostMapping("/add") 
    public Boolean add(@RequestBody Product product) {
        UserHandler principal = (UserHandler) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Users user = principal.getUsers();
        product.setCreate_admin(user.getId());
        product.setUpdate_admin(user.getId());
        Date date = new Date();
        product.setCreate_datetime(date);
        product.setUpdate_datetime(date);
        product.setCount_sale(0L);
        productMapper.insert(product);
        return true;
    }


    /**
     * 够支付产品了就生成订单并扣钱，不够不要生成订单
     * 时间
     * 卖完
     * 限购
     *
     * @return
     * @throws MyException
     */



    // 进入详情页，准入初筛并生成 value密钥
    @GetMapping("/buy/{productID}")
    public long buyTest(@PathVariable("productID") Long productID) throws MyException {

        // 获取用户信息
        UserHandler principal = (UserHandler) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Users users = principal.getUsers();

        {// 取token缓存
            Long token = RedisTool.usersToken_get(users.getId());
            if(token!=null){
                return token;
            }
        }//不存在token缓存

        // 获取产品信息
        Product product = productMapper.selectById(productID);
        Buycount buycount = buycountService.getBuycountByProduct(users,productID);

        if(buycount==null){
            buycount = buycountService.getBuycountByEngine(users,product);
        }

        long value = RedisTool.usersToken_set(users.getId(),buycount.getIs_pass());
        return value;
    }



    // 秒杀，购买
    // 通过 （value密钥 和 初筛记录）判断用户能否购买
    // 成功则 生成订单并加入消息队列
    @GetMapping("/buyreal/{productID}/{accountID}/{value}")
    public Boolean buyreal(@PathVariable("accountID") Long accountID,
                           @PathVariable("productID") Long productID,
                           @PathVariable("value") Long value) throws MyException, JsonProcessingException {


        // 获取用户信息
        UserHandler principal = (UserHandler) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Users users = principal.getUsers();

        // 校验产品
        Product product = productMapper.selectById(productID);
        if(product==null){
            throw new MyException(ResultCode.Product_Not_Exist);
        }

        // 秒杀不在时间
        if(!product.isInTime()){
            System.out.println(product);
            throw new MyException(ResultCode.Buycount_Not_In_Time);
        }
        // 秒杀在时间

        // url加密
        // 校验传入的value,即token
        TokenHelper.isValid(value, users.getId());

        if(!RedisTool.product_hasLoad(productID)){
            boolean res = RedisTool.product_load(product);
            if(!res){
                throw new MyException(ResultCode.Product_Load_Fail);
            }
        }

        {// 获取初筛数据
            QueryWrapper<Buycount> qw1 = new QueryWrapper();
            qw1.eq("users", users.getId());
            qw1.eq("product", productID);
            Buycount buycount = buycountMapper.selectOne(qw1);

            if(buycount==null) {
                // 初筛记录不存在
                throw new MyException(ResultCode.Buycount_NOT_EXIST);
            }
        }// 初筛记录存在


        // 自增尝试购买数量
        if(0 == buycountMapper.increase(users.getId(), productID)){ //自增失败，尝试次数不足
            throw new MyException(ResultCode.Buycount_Buy_Too_Much);
        };
        //正常自增

        //库存锁定
        if(0 > RedisTool.product_decHashValue(productID)){//库存不足，锁定失败
            RedisTool.product_incHashValue(productID);
            throw new MyException(ResultCode.Product_Not_Enough);
        }
        //锁定成功

        //生成订单
        Orders orders = new Orders(0L,Boolean.FALSE,product.getMoney(),Boolean.FALSE,users.getId(),accountID,productID,new Date(),null);
        ordersMapper.insert(orders);

        // 生产者生产
        producer.sendRecord(orders);
        // 删除id，要买继续进入页面
        RedisTool.userToken_delete(users.getId());

        return Boolean.TRUE;
    }

    /**
     * 修改指定产品的决策引擎
     *
     */
    @GetMapping("/engine/id/{productid_this}/{riskengineID}")
    public Boolean changeEngineById(@PathVariable("productid_this")Long productid_this,@PathVariable("riskengineID")Long riskengineID){
        // 找到目标产品
        QueryWrapper<Product> findProduct = new QueryWrapper<>();
        findProduct.eq("id", productid_this);
        Product product = productMapper.selectOne(findProduct);

        // 找到目标引擎
        QueryWrapper<engine> findEngine = new QueryWrapper<>();
        findEngine.eq("id", riskengineID);
        engine en = engineMapper.selectOne(findEngine);

        product.setEngine(riskengineID);
        en.setCount(en.getCount() + 1L);

        productMapper.updateById(product);
        engineMapper.updateById(en);
        return Boolean.TRUE;
    }

    /**
     *
     * @param productid_this
     * @param engine
     * @return
     */
    @PostMapping("/engine/obj/{productid_this}")
    public Boolean changeEngineByObject(@PathVariable("productid_this")Long productid_this,@RequestBody engine engine){
        // 创建引擎
        QueryWrapper<Product> findProduct = new QueryWrapper<>();
        findProduct.eq("id", productid_this);
        Product product = productMapper.selectOne(findProduct);
        product.setEngine(engine.getId());
        productMapper.updateById(product);
        engine.setCount(1L);
        engineMapper.insert(engine);
        return true;
    }

    /**
     *
     * @param productid_this
     * @param productid
     * @return
     */
    @GetMapping("/engine/productid/{productid_this}/{productid}")
    public Boolean changeRiskengineByProductid(@PathVariable("productid_this")Long productid_this,@PathVariable("productid")Long productid){
        Long riskengineID = productMapper.selectById(productid).getEngine();
        return changeEngineById(productid_this,riskengineID);
    }

}
